package com.piece.admin.support;

import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import com.piece.admin.model.TbSysConfig;
import com.piece.admin.service.TbSysConfigService;
import com.piece.core.web.authority.token.TokenServices;
import com.piece.core.framework.constant.ApplicationConstants;
import com.piece.core.framework.constant.FrameWorkConstants;
import com.piece.core.framework.enums.OptionType;
import com.piece.core.framework.properties.ApplicationProperties;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.util.basic.SpringUtil;
import com.piece.core.framework.util.string.StringUtil;
import com.piece.core.log.properties.LogProperties;
import com.piece.core.verifycode.config.VerifyCodeAutoConfig;
import com.piece.core.verifycode.properties.VerifyCodeProperties;
import com.piece.core.web.filter.FilterHook;
import com.piece.core.web.filter.FilterHookManager;
import com.piece.core.web.filter.XssRequestFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;

@Component
public class SiteConfigSupport {

    @Value("${spring.application.id:#{null}}")
    private String applicationId;

    @Autowired
    private ApplicationProperties applicationProperties;

    @Autowired
    private LogProperties auditLogProperties;

    @Autowired
    private VerifyCodeProperties verifyCodeProperties;

    @Resource
    private VerifyCodeAutoConfig verifyCodeAutoConfig;

    @Resource
    @Qualifier("defaultCaptcha")
    private DefaultKaptcha defaultKaptcha;

    @Resource
    private TokenServices tokenServices;

    @Resource
    private TbSysConfigService tbSysConfigService;

    @PostConstruct
    public void load() throws Exception {
        HashMap<String, Object> condition = new HashMap<>();
        condition.put("configType", OptionType.LEAF.getCode());
        List<TbSysConfig> configs = tbSysConfigService.findByCondition(condition);

        Map<String, String> map = applicationProperties.getOptions();
        map.put(ApplicationConstants.APPLICATION_ID, applicationId);
        for (TbSysConfig config: configs) {
            if (StringUtil.isNoneBlank(config.getConfigKey(), config.getConfigValue())) {
                map.put(config.getConfigKey(), config.getConfigValue());
                change(config);
            }
        }

        applicationProperties.setOptions(map);
    }

    public void reload(TbSysConfig config) {
        Map<String, String> map = applicationProperties.getOptions();
        if (OptionType.LEAF.getCode().equals(config.getConfigType()) && StringUtil.isNoneBlank(config.getConfigKey(), config.getConfigValue())) {
            map.remove(config.getConfigKey());
            map.put(config.getConfigKey(), config.getConfigValue());
            change(config);
            applicationProperties.setOptions(map);
        }
    }

    private void change(TbSysConfig config) {
        if (ApplicationConstants.SYSTEM_AUTH_LOGIN_KICK.equals(config.getConfigKey())) {
            tokenServices.setKickLogin(Convert.toBool(config.getConfigValue(), false));
        }

        if (ApplicationConstants.SYSTEM_AUTH_TOKEN_MAXIMUM.equals(config.getConfigKey())) {
            tokenServices.setMaximum(Convert.toInt(config.getConfigValue(), 1));
        } else if (ApplicationConstants.KAPTCHA_LENGTH.equals(config.getConfigKey())) {
            int captchaLength = Convert.toInt(config.getConfigValue());
            Properties properties = new Properties();
            verifyCodeAutoConfig.generateDefaultProperties(properties, captchaLength);
            defaultKaptcha.setConfig(new Config(properties));
        } else if (ApplicationConstants.XSS_EXCLUDE_URL.equals(config.getConfigKey())) {
            XssRequestFilter xssFilter = SpringUtil.getBean(XssRequestFilter.class);
            xssFilter.setExcludes(Convert.toStrList(config.getConfigValue(), FrameWorkConstants.SPLIT_PARAM));
            changeFilterHook(xssFilter);
        } else if (ApplicationConstants.XSS_ILLEGAL_PARAM.equals(config.getConfigKey())) {
            XssRequestFilter xssFilter = SpringUtil.getBean(XssRequestFilter.class);
            xssFilter.setIllegalParam(Convert.toStrArray(config.getConfigValue()));
            changeFilterHook(xssFilter);
        }
    }

    private void changeFilterHook(FilterHook filterHook) {
        FilterHookManager filterHookManager = SpringUtil.getBean(FilterHookManager.class);
        if (null != filterHookManager) {
            filterHookManager.removeFilterHook(filterHook);
            filterHookManager.addFilterHook(filterHook);
        }
    }
}
